﻿Imports System.Drawing
Imports System.Drawing.Imaging

''' <summary>
''' 播放gif 动画控件
''' </summary>
''' <remarks></remarks>
Public Class CtlAnimator

#Region " 动画控制 变量"

    Private DoorClose As Bitmap = Nothing
    Private anType As AnimateTypes = AnimateTypes.Closed    '' 库门关闭         
    Private FrameCount = 10                                 '' 最后GIF帧数量
    Private Frames(9) As Image
    Private CurrentImage As Image                           '' 当前的图片
    Private CurrentIndex As Integer = 0                     '' 当前帧
    Private RotateFlip As RotateFlipType                    '' 图片旋转与反转

#End Region

#Region "方法"

    Sub New()

        SetStyle(ControlStyles.UserPaint, True)
        SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)

        ' 此调用是 Windows 窗体设计器所必需的。
        InitializeComponent()

        ' 在 InitializeComponent() 调用之后添加任何初始化。
        '
        InitFrames()
        CurrentImage = Frames(0)

    End Sub

    ''' <summary>
    ''' 初始化帧
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InitFrames()
        Frames(0) = My.Resources.Door_0.Clone
        Frames(1) = My.Resources.Door_1.Clone
        Frames(2) = My.Resources.Door_2.Clone
        Frames(3) = My.Resources.Door_3.Clone
        Frames(4) = My.Resources.Door_4.Clone
        Frames(5) = My.Resources.Door_5.Clone
        Frames(6) = My.Resources.Door_6.Clone
        Frames(7) = My.Resources.Door_7.Clone
        Frames(8) = My.Resources.Door_8.Clone
        Frames(9) = My.Resources.Door_9.Clone
    End Sub

    ''' <summary>
    ''' 旋转与翻转
    ''' </summary>
    ''' <param name="rf"></param>
    ''' <remarks></remarks>
    Private Sub RotateFilpImage(ByVal rf As RotateFlipType)
        For index As Integer = 0 To 9
            Frames(index).RotateFlip(rf)
        Next
        CurrentImage = Frames(0)
    End Sub


    Public Property RotateFilp() As RotateFlipType
        Get
            Return RotateFlip
        End Get
        Set(ByVal value As RotateFlipType)
            InitFrames()
            RotateFlip = value
            RotateFilpImage(value)
            Me._ici.UnitMsg = CType(value, Integer).ToString()
            Me.Invalidate()
        End Set
    End Property


    ''' <summary>
    ''' 打开
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Open()
        If (anType = AnimateTypes.Opening Or anType = AnimateTypes.Opened) Then
            Exit Sub
        End If

        anType = AnimateTypes.Opening
        CurrentIndex = 0
        CurrentImage = Frames(CurrentIndex)
        Me.Invalidate()
        StartAnimate()
    End Sub

    ''' <summary>
    ''' 关闭
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Close()
        If (anType = AnimateTypes.Closing Or anType = AnimateTypes.Closed) Then
            Exit Sub
        End If

        anType = AnimateTypes.Closing
        CurrentIndex = FrameCount - 1
        CurrentImage = Frames(CurrentIndex)
        Me.Invalidate()
        StartAnimate()
    End Sub

    Private Sub TestColse()

    End Sub

    ''' <summary>
    ''' 重绘界面
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

        e.Graphics.DrawImage(CurrentImage, 1, 1, Width - 2, Height - 2)
        '#If DEBUG Then
        '        e.Graphics.DrawString(CurrentIndex.ToString, New Font("宋体", 9, FontStyle.Bold, GraphicsUnit.Point), Brushes.Black, 10, 10)
        '#End If
        If (Me._IsDesign) Then
            e.Graphics.DrawRectangle(Pens.Black, 1, 1, Width - 2, Height - 2)
        End If
    End Sub

    ''' <summary>
    ''' 开始动画
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub StartAnimate()
        Timer1.Start()
    End Sub


    ''' <summary>
    ''' 停止动画
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub StopAnimate()


        If (anType = AnimateTypes.Closing) Then
            anType = AnimateTypes.Closed
            CurrentIndex = 0
        End If
        If (anType = AnimateTypes.Opening) Then
            anType = AnimateTypes.Opened
            CurrentIndex = FrameCount - 1

        End If

        CurrentImage = Frames(CurrentIndex)
        Me.Invalidate(Me.Region)
    End Sub

    Private Sub ForceStop()
        Timer1.Stop()

        If (anType = AnimateTypes.Closing) Then
            anType = AnimateTypes.Closed
            CurrentIndex = 0
        End If
        If (anType = AnimateTypes.Opening) Then
            anType = AnimateTypes.Opened
            CurrentIndex = FrameCount - 1

        End If

        CurrentImage = Frames(CurrentIndex)
        Me.Invalidate(Me.Region)
    End Sub

    '''' <summary>
    '''' 图片信息
    '''' </summary>
    '''' <param name="image"></param>
    '''' <remarks></remarks>
    'Private Sub ImageInfo(ByVal image As Image)
    '    Dim frameDelay() As Integer

    '    FrameCount = image.GetFrameCount(FrameDimension.Time)
    '    ReDim frameDelay(FrameCount - 1)

    '    Dim frameDelayItem As PropertyItem = image.GetPropertyItem(PropertyTagFrameDelay)

    '    ' If the image does not have a frame delay, we just return 0. 
    '    '
    '    FrameTimer = 0
    '    Dim idelay As Integer = 0
    '    If (frameDelayItem IsNot Nothing) Then
    '        ' Convert the frame delay from byte[] to int
    '        '
    '        Dim values() As Byte = frameDelayItem.Value

    '        Debug.Assert(values.Length = 4 * FrameCount, "PropertyItem has invalid value byte array")


    '        For i As Integer = 0 To FrameCount - 1 Step 1
    '            frameDelay(i) = values(i * 4) + 256 * values(i * 4 + 1) + 256 * 256 * values(i * 4 + 2) + 256 * 256 * 256 * values(i * 4 + 3)
    '            If (frameDelay(i) = 0) Then
    '                idelay += 5
    '            Else
    '                If (frameDelay(i) Mod 5) = 0 Then
    '                    idelay += frameDelay(i)
    '                Else
    '                    idelay += (frameDelay(i) / 5) * 5
    '                End If

    '            End If
    '        Next
    '    End If
    '    FrameTimer = idelay

    'End Sub


    ''' <summary>
    ''' 动画状态
    ''' </summary>
    ''' <remarks></remarks>
    Friend Enum AnimateTypes
        Closed
        Closing
        Opened
        Opening
    End Enum


    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        If Not (CurrentIndex >= FrameCount Or CurrentIndex < 0) Then
            CurrentImage = Frames(CurrentIndex)
        Else

            Timer1.Stop()
            StopAnimate()
        End If

        If (anType = AnimateTypes.Closing) Then
            CurrentIndex -= 1
        ElseIf (anType = AnimateTypes.Opening) Then
            CurrentIndex += 1
        End If
        Me.Invalidate()

    End Sub
#End Region

#Region "Event"

    Private _ici As ImgControlItem                  '' 包括的ImgcontrolItem 对象
    Private _IsDesign As Boolean = False                    '当前是否出于设计状态 

    Public Event DeleteEvent As EventHandler         '' 删除对象事件
    Public Event ShowDetailsEvent As EventHandler   '' 显示详细信息事件

    Public Property IsDesign() As Boolean
        Get
            Return _IsDesign
        End Get
        Set(ByVal value As Boolean)
            _IsDesign = value
        End Set
    End Property

    ''' <summary>
    ''' Img控件对象数据
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ImgControlItem() As ImgControlItem
        Get
            Return _ici
        End Get
        Set(ByVal value As ImgControlItem)
            _ici = value.Clone()
            _ici.DataType = 4
            InitControl()
        End Set
    End Property

    ''' <summary>
    ''' 设置提示
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InitControl()
        Me.ToolTip1.SetToolTip(Me, _ici.TipMsg)

        Try
            Me.RotateFilp = CType(Convert.ToInt32(_ici.UnitMsg), RotateFlipType)
        Catch ex As Exception
            Me.RotateFilp = RotateFlipType.RotateNoneFlipNone
        End Try

    End Sub

    '' 删除事件传递
    Protected Overrides Sub OnKeyUp(ByVal e As System.Windows.Forms.KeyEventArgs)
        MyBase.OnKeyUp(e)
        If (e.KeyCode = Keys.Delete) Then
            RaiseEvent DeleteEvent(Me, New EventArgs())
        End If
    End Sub

    '' 传递显示明细
    Protected Overrides Sub OnMouseDoubleClick(ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseDoubleClick(e)
        RaiseEvent ShowDetailsEvent(Me, New EventArgs())
    End Sub

    Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
        MyBase.OnSizeChanged(e)
        Me.Invalidate(Me.Region)
    End Sub

    Private Sub CtlAnimator_MouseHover(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.MouseHover

        'If (Me._IsDesign) Then
        '    Me.ToolTip1.Show(_ici.TipMsg, Me)
        'End If
    End Sub

    Private Sub cmMain_Opening(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles cmMain.Opening
        e.Cancel = Not _IsDesign
    End Sub

    Private boolFilp As Boolean = False
    Private angle As Integer = 0
    Private Sub menXAnticlockwise_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        boolFilp = False
        angle = 0
        Me.RotateFilp = RotateFlipType.RotateNoneFlipNone

    End Sub

    Private Sub menXClockwise_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        boolFilp = True
        angle = 0
        Me.RotateFilp = RotateFlipType.RotateNoneFlipX

    End Sub

    Private Sub menYAnticlockwise_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        boolFilp = False
        angle = 90
        Me.RotateFilp = RotateFlipType.Rotate90FlipNone

    End Sub

    Private Sub menYclockwise_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        boolFilp = True
        angle = 90
        Me.RotateFilp = RotateFlipType.Rotate90FlipX

    End Sub

    Private Sub men180_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        angle += 180
        angle = angle Mod 360
        If (boolFilp) Then
            Select Case angle
                Case 0
                    Me.RotateFilp = RotateFlipType.RotateNoneFlipX

                Case 90
                    Me.RotateFilp = RotateFlipType.Rotate90FlipX
                Case 180
                    Me.RotateFilp = RotateFlipType.Rotate180FlipX
                Case 270
                    Me.RotateFilp = RotateFlipType.Rotate270FlipX

            End Select
        Else
            Select Case angle
                Case 0
                    Me.RotateFilp = RotateFlipType.RotateNoneFlipNone
                Case 90
                    Me.RotateFilp = RotateFlipType.Rotate90FlipNone
                Case 180
                    Me.RotateFilp = RotateFlipType.Rotate180FlipNone
                Case 270
                    Me.RotateFilp = RotateFlipType.Rotate270FlipNone
            End Select
        End If

    End Sub

#End Region


    Private Sub menOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menOpen.Click
        Close()
        Open()
    End Sub

    Private Sub menLeft_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menLeft.Click
        angle = 90
        UpdateRoute()
    End Sub

    Private Sub menTop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menTop.Click
        angle = 180
        UpdateRoute()
    End Sub

    Private Sub menRight_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menRight.Click
        angle = 270
        UpdateRoute()
    End Sub


    Private Sub menButtom_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menButtom.Click
        angle = 0
        UpdateRoute()
    End Sub

    Private Sub menClockwise_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menClockwise.Click
        boolFilp = True
        UpdateRoute()
    End Sub

    Private Sub menAntclockwise_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menAntclockwise.Click
        boolFilp = False
        UpdateRoute()
    End Sub

    Private Sub UpdateRoute()
        If (boolFilp) Then
            Select Case angle
                Case 0
                    Me.RotateFilp = RotateFlipType.RotateNoneFlipX
                Case 90
                    Me.RotateFilp = RotateFlipType.Rotate90FlipY
                Case 180
                    Me.RotateFilp = RotateFlipType.Rotate180FlipX
                Case 270
                    Me.RotateFilp = RotateFlipType.Rotate270FlipY
            End Select
        Else
            Select Case angle
                Case 0
                    Me.RotateFilp = RotateFlipType.RotateNoneFlipNone
                Case 90
                    Me.RotateFilp = RotateFlipType.Rotate90FlipNone

                Case 180
                    Me.RotateFilp = RotateFlipType.Rotate180FlipNone
                Case 270
                    Me.RotateFilp = RotateFlipType.Rotate270FlipNone
            End Select
        End If
    End Sub

End Class
